package cn.hrbnu.service.impl;

import cn.hrbnu.enums.AppHttpCodeEnum;
import cn.hrbnu.exception.SystemException;
import cn.hrbnu.mapper.UserMapper;
import cn.hrbnu.po.User;
import cn.hrbnu.service.UserService;
import cn.hrbnu.util.ResponseResult;
import cn.hrbnu.vo.UserInfoVo;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @author zhangyadong
 * @version 1.0
 * &#064;ClassName  UserServiceImpl
 * &#064;date  2025-06-11 9:17
 */

@Service
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;

    private final RedisTemplate<String,String> redisTemplate;

    public UserServiceImpl(UserMapper userMapper, RedisTemplate<String, String> redisTemplate) {
        this.userMapper = userMapper;
        this.redisTemplate = redisTemplate;
    }


    /**
     * 用户登录方法
     * <p>
     * 该方法用于验证用户身份，生成并返回登录令牌（token）和用户信息
     * 它首先根据用户名查询用户信息，然后比较密码，最后生成token并保存用户信息到Redis
     *
     * @param user 包含用户名和密码的用户对象，用于进行登录验证
     * @return 返回一个ResponseResult对象，包含登录结果和相关数据
     */
    @Override
    public ResponseResult<Object> login(User user) {
        //1,查询用户名和密码
        User u1 = userMapper.getByName(user.getUserName());
        if (u1==null){
            return new ResponseResult<>().errorResult(AppHttpCodeEnum.LOGIN_ERROR);
        }

        //2,验证用户名和密码
        String pass = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        if (!u1.getPassword().equals(pass)){
            return new ResponseResult<>().errorResult(AppHttpCodeEnum.LOGIN_ERROR);
        }

        //3,正确 ：生成token  保存进redis  返回token和用户信息
        String token = UUID.randomUUID().toString().replaceAll("-", "");

        //4,保存进redis  返回token和用户信息
        redisTemplate.opsForValue().set("user:login:"+token, JSON.toJSONString(u1));



        Map<String,Object> map=new HashMap<>();
        UserInfoVo userVo=new UserInfoVo();
        BeanUtils.copyProperties(u1,userVo);
        map.put("token",token);
        map.put("userInfo",userVo);

        return new ResponseResult<>(200,"操作成功",map);
    }

    /**
     * 处理用户注销请求
     * 该方法通过删除Redis中的用户登录状态来实现用户注销功能
     *
     * @param request HTTP请求对象，用于获取请求头中的Token信息
     * @return 返回一个包含注销结果信息的ResponseResult对象
     */
    @PostMapping("/logout")
    public ResponseResult<Object> logout(HttpServletRequest request) {
        //从请求头中获取Token
        String token = request.getParameter("Token");
        //从Redis中删除与该Token关联的用户登录状态
        redisTemplate.delete("user:login:"+token);
        //返回注销成功的信息
        return new ResponseResult<>(200,"注销成功");
    }

    /**
     * 根据token获取用户信息
     *
     * @param token 用户登录令牌，用于标识用户会话
     * @return 返回包含用户信息的ResponseResult对象
     */
    @Override
    public ResponseResult<Object> userInfo(String token) {
        // 从Redis中获取登录用户信息
        String s = redisTemplate.opsForValue().get("user:login:" + token);
        // 将获取到的JSON字符串转换为User对象
        User user = JSON.parseObject(s, User.class);

        // 创建一个UserInfoVo对象用于封装用户信息
        UserInfoVo userInfoVo = new UserInfoVo();
        // 将User对象的属性值复制到UserInfoVo对象中
        if (user != null) {
            BeanUtils.copyProperties(user, userInfoVo);
        }

        // 返回包含用户信息的ResponseResult对象
        return new ResponseResult<>(200, "操作成功", userInfoVo);
    }

    /**
     * 更新用户信息
     * <p>
     * 该方法接收一个User对象作为参数，利用userMapper更新数据库中的用户信息
     * 主要用于在用户信息发生变化时，同步更新到数据库中，确保数据的一致性
     *
     * @param user 需要更新的用户对象，包含用户的相关信息
     * @return 返回一个ResponseResult对象，表示更新操作的结果
     */
    @Override
    public ResponseResult<Object> updateUserInfo(User user) {
        userMapper.updateById(user);
        return new ResponseResult<>().okResult();
    }

    /**
     * 用户注册功能
     * <p>
     * 该方法用于处理用户注册请求，包括验证用户输入信息的完整性、检查用户名的唯一性，
     * 以及对用户密码进行加密处理后存储到数据库中
     *
     * @param user 用户对象，包含用户提交的注册信息，如用户名、密码、邮箱和昵称
     * @return 返回注册结果，如果注册成功，则返回成功地响应结果
     * @throws SystemException 如果用户名、密码、邮箱或昵称为空，或用户名已存在，则抛出系统异常
     */
    @Override
    public ResponseResult<Object> register(User user) {
        // 对数据进行非空判断
        if (!StringUtils.hasText(user.getUserName())) {
            throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
        }
        if (!StringUtils.hasText(user.getPassword())) {
            throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
        }
        if (!StringUtils.hasText(user.getEmail())) {
            throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
        }
        if (!StringUtils.hasText(user.getNickName())) {
            throw new SystemException(AppHttpCodeEnum.REQUIRE_USERNAME);
        }

        // 检查用户名是否已存在
        int count = userMapper.selByEmail(user.getEmail());
        if (count > 0) {
            throw new SystemException(AppHttpCodeEnum.USERNAME_EXIST);
        }

        // 对用户密码进行MD5加密
        String s = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(s);
        // 设置用户未删除状态
        user.setDelFlag(0);
        // 保存用户到数据库
        userMapper.save(user);

        // 返回成功注册的响应结果
        return new ResponseResult<>().okResult();
    }
}